/*
* uart.c
*
* Created: 2012-11-28 20:58:01
*  Author: ant
*/

#include "uart.h"
#include <stdlib.h>

u8 r_buff[32];
u8 t_buff[32];
u8 rx_len = 0;
u8 tx_len = 0;
u8 cur_tx = 0;
u8 uart_err_cnt = 0;
u16 sens_value = 200;


#define RS_WAIT 104
#define RS_WAIT_RF 40
#define RS_WAIT_R 61

char last_cmd[24];



void send_command()
{

	static u8 err = 0;
	switch (spec_aquire)
	{
		case  CALIB_FACT:
		{
			set_clock_high();
			prep_recv();
			send("INIT\r",5);
			aquire = CALIB_FACT_WAIT;
			spec_aquire = 0;
			return;
			break;
		}
		
		case  CALIB_ZERO:
		{
			eep_cnt = read_word(EEP_PTR);
			
			if (eep_cnt > MAX_EEPROM)
				eep_cnt = EEP_PTR + 2;
				
			_write(eep_cnt,'Z');
			eep_cnt++;
			write_word(eep_cnt, t_pom);
			eep_cnt+=2;
			write_word(EEP_PTR,eep_cnt);
						
			set_clock_high();
			prep_recv();
			send("ZERO2\r",6);

			aquire = CALIB_ZERO_WAIT;
			spec_aquire = 0;
			

			
			return;
			break;
		}
		
		case  CALIB_SENSE:
		{
			eep_cnt = read_word(EEP_PTR);
			if (eep_cnt > MAX_EEPROM)
				eep_cnt = EEP_PTR + 2;
			
			_write(eep_cnt,'S');
			eep_cnt++;
			write_word(eep_cnt,sens_value);
			eep_cnt+=2;
			write_word(eep_cnt, t_pom);
			eep_cnt+=2;
			write_word(EEP_PTR,eep_cnt);
			
			char cmd[20];
			char val[10];
			itoa(sens_value,cmd,10);
			val[0] = 0;
			for (u8 c = 0; c < (4 - strlen(cmd));c++)
			{
				strcat(val,"0");
			}
			strcat(val,cmd);
			
			strcpy(cmd,"CALB ");
			strcat(cmd,val);
			strcat(cmd,"\r");
			
			strcpy(last_cmd,cmd);

			
			aquire = CALIB_SENSE_WAIT;
			spec_aquire = 0;
			set_clock_high();
			prep_recv();
			send(cmd,strlen(cmd));	
				
			return;
			break;
		}
		case NORMAL_MODE:
		{
			break;
		}
	}	
	
	switch(aquire)
	{
		case NORMAL_MODE:
		{
			err = 0;
			TR_P_DISABLE;
			
			set_clock_high();
			prep_recv();
			send("DATAE\r",6);

			aquire = ASKED_MODE;
			
		}
		break;
		case ASKED_MODE:		// no response after 876 * (8M / 1024) - ~0.1s
		{
			err ++;
			if (err < 4)
			{
				set_clock_high();
				prep_recv();
				send("DATAE\r",6);
				break;
			}
			else
			{
				set_clock_low();
				//err = 0;
				t_pom = 500;
				t_pom |= (1 << 14) ;
				TR_P_ENABLE;
			}
			if (err > 12)
			{
				aquire = NORMAL_MODE;
				spec_aquire = NORMAL_MODE;
				err = 0;
			}				
			break;
		}
	}
}

void recv_spec()
{
	if (aquire == CALIB_SENSE_WAIT)
	{

		r_buff[rx_len] = 0;	// add /0
		
		char cmp[20];
		
		u8 len = strlen((char*)r_buff);
		
		if (len < 8)
		{
			err++;
			if (err < 5)
			{
				spec_aquire = CALIB_SENSE;
				aquire = NORMAL_MODE;
				return;
			}
			return;
		}
		
		strcpy(cmp, ((char*)r_buff) + (len - 3));
		if (strcmp(cmp,"OK\r") == 0)
		{
			err = 0;
			t_pom = CODE_SENS;
			aquire = NORMAL_MODE;
			save_next = 1;
			WAITMS(1000);
			return;
		}

		
		strcpy(cmp, ((char*)r_buff) + (len - 6));
		if (strcmp(cmp,"FAULT\r") == 0)
		{
			t_pom = CODE_SERVC;
			aquire = NORMAL_MODE;
			
			if (eep_cnt > MAX_EEPROM)
				eep_cnt = EEP_PTR + 2;
			_write(eep_cnt,'s');
			eep_cnt++;
			write_word(EEP_PTR,eep_cnt);			
			
			WAITMS(1000);
			return;
		}
		err++;
		if (err < 5)
		{
			spec_aquire = CALIB_SENSE;
			aquire = NORMAL_MODE;
			return;
		}
		aquire = NORMAL_MODE;
		err = 0;
		return;
	}
	
	
	if (aquire == CALIB_FACT_WAIT)
	{
		//static u16 mem  = 533;
		r_buff[8] = 0;
		/*
		u8 len = strlen((char*)r_buff);
		_write(mem,len);
		mem++;
		
		for (u8 c = 0; c < len; c++)
		{
			_write(mem,r_buff[c]);
			mem++;
		}
		*/
		char cmp[11];
		strcpy(cmp,"INIT OK\r");
		
		if (strcmp((char*)r_buff,cmp) != 0)	// failed
		{
			// failed 
			if (err < 5)
			{
				spec_aquire = CALIB_FACT;		// repeat
				aquire = NORMAL_MODE;
			}
			else
			{
				aquire = NORMAL_MODE;
				t_pom = CODE_ERR;
			}
			err++;
			return;
		}
		
		aquire = NORMAL_MODE;
		t_pom = CODE_FACT;
		WAITMS(1000);
		
		return;
	}

	if (aquire == CALIB_ZERO_WAIT)
	{
		r_buff[rx_len] = 0;		// add \0
		
		char cmp[22];
		strcpy(cmp,"ZERO2 FAULT\r");	
		
		if (strcmp(cmp,(char*)r_buff) == 0)	// FAULT ?
		{
			t_pom = CODE_SERVZ;
			aquire = NORMAL_MODE;

			if (eep_cnt > MAX_EEPROM)
			eep_cnt = EEP_PTR + 2;
			
			_write(eep_cnt,'z');
			eep_cnt++;
			write_word(EEP_PTR,eep_cnt);
			err = 0;

			WAITMS(1000);
			return;
		}
		strcpy(cmp,"ZERO2 OK\r");	
		if (strcmp((char*)r_buff,cmp) == 0)		// ok
		{
			save_next = 1;
			t_pom = CODE_ZERO;
			aquire = NORMAL_MODE;
			err = 0;
			WAITMS(1000);
			return;
		}

		err++;
		if (err < 5)
		{
			spec_aquire = CALIB_ZERO;
			aquire = NORMAL_MODE;
			return;
		}
		aquire = NORMAL_MODE;
		err = 0;
		return;
	}



}

void recv_data()
{
	i16 conc = 0;
	u8 status = 0;
	TR_P_ENABLE;
	aquire &= ~(FINISH_MODE);
	
	swl_clear();
	swl_printi(aquire);
	swl_print(";");
	swl_printi(spec_aquire);
	swl_print("L");
	swl_printi(rx_len);
	swl_print(";");
	
	
	switch(aquire)
	{
		case CALIB_FACT_WAIT:
			recv_spec();
		break;
		case CALIB_ZERO_WAIT:
			recv_spec();
		break;
		case CALIB_SENSE_WAIT:
			recv_spec();
		break;
	}
	
	if (aquire == ASKED_MODE)	// asked for data
	{
		conc = r_buff[0];
		conc = conc << 8; 
		conc |= r_buff[1];
		status = r_buff[2];
		
		swl_print(";");
		swl_printi(conc);
		swl_print(";");
		swl_setpos(16);
		swl_printi(r_buff[2]);
		swl_print(";");
		swl_printi(r_buff[3]);
		swl_print(";");
		swl_printi(r_buff[4]);
		swl_print(";");
		
		cli();
		crc_data_len = 0;
		u8 crcc = 0;
		for (u8 c = 0; c < 3; c++)
		{
			crcc = crcc ^ r_buff[c];
		}

		if (crcc != r_buff[3])
		{
			err ++;
			uart_err_cnt++;
			swl_print("!CRC!");
			swl_proceed();
			return;
		}
		else
		{
			err = 0;
		}
		
		swl_printi(crcc);
		swl_print(";");

		if (conc == -32767)
		{
			t_pom = CODE_INIT;
			err = 0;
			return; 
		}
	}

	for (u8 c = 0; c < 10; c++)
	r_buff[c] = 0xFA;
	
	if (err > 20)
	{
		t_pom = CODE_ERR;
		swl_print("err");
		swl_proceed();
		return;
	}
	

	if (conc < 500)
	{
		t_pom = conc;
		t_pom |= (1 << 14);
		if (status & 0x3f)		// temp & other stuff
			t_pom |= (1 << 12);
	}
	else
	{
		t_pom = conc / 10;
		t_pom |= (1 << 15);
		if (status & 0x3f)		// temp & other stuff
			t_pom |= (1 << 13);
	}

	static u8 delay = 0;

	if (save_next)
	{
		delay++;
		if (delay < 3)
			return;
		delay = 0;

		eep_cnt = read_word(EEP_PTR);
		if (eep_cnt > MAX_EEPROM)
			eep_cnt = EEP_PTR + 2;

		_write(eep_cnt,'a');
		eep_cnt++;
		write_word(eep_cnt,t_pom);
		eep_cnt+=2;
		write_word(EEP_PTR,eep_cnt);
		save_next = 0;
	}
	else
	{
		delay = 0;
	}
	swl_proceed();
	
}



void prep_recv()
{
	PORTD |= (1 << 1);		// TXD
	UBRR0 = 51;//UART_BAUD_CALC(9600,3686400) -1;
	/* Enable receiver and transmitter */
	UCSR0B = (1<<RXCIE0);
	/* Set frame format: 8data, 2stop bit */
	UCSR0C = (1<<UCSZ00)|(1<<UCSZ01);		// 8bit, 1 stop

	//DDRD |= (1 << 1);			// TXD0
	UCSR0B |= (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0);
	//WAITMS(1);
	rx_len = 0;
}

void send(char* data, u8 len)
{

	LY_ON;
	
	memcpy(t_buff,data,len);
	tx_len = len;
	cur_tx = 1;
	
	//PORTD |= (1 << 1) | (1 << )
	rx_len = 0;
	
	for ( u8 c = 0; c < len; c++)
	{
		UDR0 = t_buff[c];
		_delay_us(1740);
		while ( !( UCSR0A & (1<<UDRE0)) );
	}
	LY_OFF;
	//UDR0 = t_buff[0];
	//_delay_ms(400);		// wait 400/8 = 50ms
	//UCSR0C = 0;
	//UCSR0B = 0;
	TCNT2 = 0;
	T2_RUN;
	
}

void set_clock_high()
{
	cli();
	CLKPR = (1 << CLKPCE);
	CLKPR = 0;
	sei();
}

void set_clock_low()
{
	cli();
	CLKPR = (1 << CLKPCE);
	CLKPR = 3;		// div 8 (1.00MHz)
	sei();
}


void search_eep()
{
	eep_cnt = read_word(EEP_PTR);
	if (eep_cnt > MAX_EEPROM)		// (MAX_EEPROM-128)
	{
		eep_cnt = 2 + EEP_PTR;
	}
	if (eep_cnt < EEP_PTR)
		eep_cnt = 2 + EEP_PTR;
	
	
}

u8 err = 0;
u8 save_next = 0;



u16 timer_cnt = 0;
u16 timer_cnt_h = 0;

